#include "timer_wheel.h"
#include <cstdlib>
#include <iostream>

// 每层的时间跨度 (256^level)
// 4层级对应的跨度分别为: 1, 256, 65536, 16777216, 4294967296
static const uint64_t WHEEL_SPANS[] = {1, 256, 65536, 16777216, 4294967296};

TimerWheel::TimerWheel() : timeticket(0), running(true)
{
    // 初始化所有4个层级的槽位为nullptr
    for (int i = 0; i < WHEEL_LEVELS; ++i) {
        wheels[i].fill(nullptr);
    }
    // 启动工作线程
    worker = std::thread(&TimerWheel::workerThread, this);
}

TimerWheel::~TimerWheel()
{
    // 停止工作线程
    running = false;
    cv.notify_one();
    if (worker.joinable()) {
        worker.join();
    }
    
    // 清理所有4个层级的任务
    for (int i = 0; i < WHEEL_LEVELS; ++i) {
        for (auto& slot : wheels[i]) {
            while (slot != nullptr) {
                TimerElem* temp = slot;
                slot = slot->next;
                free(temp);
            }
        }
    }
    
    // 清理任务队列
    std::lock_guard<std::mutex> lock(queueMutex);
    while (!taskQueue.empty()) {
        TimerElem* elem = taskQueue.front();
        taskQueue.pop();
        
        while (elem != nullptr) {
            TimerElem* temp = elem;
            elem = elem->next;
            free(temp);
        }
    }
}

void TimerWheel::addTimer(cb callback, void* puser, uint64_t interval)
{
    if (interval == 0 || callback == nullptr) {
        return;
    }
    
    TimerElem* elem = (TimerElem*)malloc(sizeof(TimerElem));
    if (elem == nullptr) {
        return;
    }
    
    uint64_t expire = timeticket + interval;
    elem->callback = callback;
    elem->puser = puser;
    elem->interval = interval;
    elem->expire = expire;
    elem->next = nullptr;
    
    std::lock_guard<std::mutex> lock(queueMutex);
    
    // 确定任务应该放入哪个层级（0-3层）
    int level = 0;
    uint64_t current_span = WHEEL_SPANS[1]; // 从第二层级的跨度开始比较
    
    // 最多到第3层（因为WHEEL_LEVELS=4，索引0-3）
    while (level < WHEEL_LEVELS - 1 && interval >= current_span) {
        level++;
        current_span *= SLOT_COUNT;
    }
    
    // 计算在该层级中的槽位
    uint64_t wheel_base = timeticket / WHEEL_SPANS[level];
    uint8_t slot = static_cast<uint8_t>((expire / WHEEL_SPANS[level]) % SLOT_COUNT);
    
    // 插入到槽位链表头部
    elem->next = wheels[level][slot];
    wheels[level][slot] = elem;
}

void TimerWheel::cascade(uint8_t level, uint8_t slot)
{
    // 将指定层级的槽位中所有任务迁移到低层级
    TimerElem* current = wheels[level][slot];
    wheels[level][slot] = nullptr;
    
    while (current != nullptr) {
        TimerElem* next = current->next;
        current->next = nullptr;
        
        // 尝试将任务放入更低的层级
        uint64_t interval = current->expire - timeticket;
        int target_level = 0;
        uint64_t current_span = WHEEL_SPANS[1];
        
        while (target_level < level - 1 && interval >= current_span) {
            target_level++;
            current_span *= SLOT_COUNT;
        }
        
        // 计算目标层级的槽位
        uint64_t wheel_base = timeticket / WHEEL_SPANS[target_level];
        uint8_t target_slot = static_cast<uint8_t>((current->expire / WHEEL_SPANS[target_level]) % SLOT_COUNT);
        
        // 插入到目标槽位
        current->next = wheels[target_level][target_slot];
        wheels[target_level][target_slot] = current;
        
        current = next;
    }
}

void TimerWheel::tick()
{
    std::lock_guard<std::mutex> lock(queueMutex);
    uint8_t slot = static_cast<uint8_t>(timeticket % SLOT_COUNT);
    
    // 处理第0层的当前槽位
    if (slot == 0 && timeticket != 0) {
        // 第0层轮转一圈，需要级联处理上层（1-3层）
        for (int level = 1; level < WHEEL_LEVELS; ++level) {
            uint8_t upper_slot = static_cast<uint8_t>((timeticket / WHEEL_SPANS[level]) % SLOT_COUNT);
            cascade(level, upper_slot);
            
            // 如果上层槽位不是0，不需要继续向上级联
            if (upper_slot != 0) {
                break;
            }
        }
    }
    
    // 将第0层当前槽位的任务放入执行队列
    TimerElem* current = wheels[0][slot];
    wheels[0][slot] = nullptr;
    
    if (current != nullptr) {
        taskQueue.push(current);
        cv.notify_one();
    }
    
    timeticket++;
}

void TimerWheel::workerThread()
{
    while (running) {
        std::unique_lock<std::mutex> lock(queueMutex);
        
        cv.wait(lock, [this] { 
            return !taskQueue.empty() || !running; 
        });
        
        if (!running) {
            break;
        }
        
        TimerElem* current = taskQueue.front();
        taskQueue.pop();
        lock.unlock();
        
        while (current != nullptr) {
            TimerElem* next = current->next;
            current->next = nullptr;
            
            try {
                current->callback(current->puser);
            } catch (...) {
                std::cerr << "Error executing timer callback" << std::endl;
            }
            
            // 周期性任务重新添加
            if (current->interval > 0) {
                std::lock_guard<std::mutex> addLock(queueMutex);
                uint64_t new_expire = timeticket + current->interval;
                current->expire = new_expire;
                
                // 重新计算层级和槽位
                int level = 0;
                uint64_t current_span = WHEEL_SPANS[1];
                
                while (level < WHEEL_LEVELS - 1 && current->interval >= current_span) {
                    level++;
                    current_span *= SLOT_COUNT;
                }
                
                uint64_t wheel_base = timeticket / WHEEL_SPANS[level];
                uint8_t slot = static_cast<uint8_t>((new_expire / WHEEL_SPANS[level]) % SLOT_COUNT);
                
                current->next = wheels[level][slot];
                wheels[level][slot] = current;
            } else {
                free(current);
            }
            
            current = next;
        }
    }
}
